(* deprecated: this is used by Semgrep.dump_v_format to expose the AST to
 * Semgrep playground!
 * Use AST_generic.show_any instead.
 *)
open Fpath_.Operators
open Tok
open AST_generic

(* was in meta_parse_info.ml before *)
type dumper_precision = {
  full_info : bool;
  token_info : bool;
  type_info : bool;
}

let default_dumper_precision =
  { full_info = false; token_info = false; type_info = false }

let vof_filename v = OCaml.vof_string v

let vof_token_location
    {
      Tok.str = v_str;
      pos =
        {
          bytepos = v_charpos;
          line = v_line;
          column = v_column;
          file = v_file;
          _;
        };
    } =
  let bnds = [] in
  let arg = vof_filename !!v_file in
  let bnd = ("file", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_int v_column in
  let bnd = ("column", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_int v_line in
  let bnd = ("line", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_int v_charpos in
  let bnd = ("bytepos", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_string v_str in
  let bnd = ("str", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

let vof_token_origin = function
  | OriginTok v1 ->
      let v1 = vof_token_location v1 in
      OCaml.VSum ("OriginTok", [ v1 ])
  | FakeTok (v1, opt) ->
      let v1 = OCaml.vof_string v1 in
      let opt =
        OCaml.vof_option
          (fun (p1, i) ->
            OCaml.VTuple [ vof_token_location p1; OCaml.vof_int i ])
          opt
      in
      OCaml.VSum ("FakeTok", [ v1; opt ])
  | Ab -> OCaml.VSum ("Ab", [])
  | ExpandedTok (v1, (v2, v3)) ->
      let v1 = vof_token_location v1 in
      let v2 = vof_token_location v2 in
      let v3 = OCaml.vof_int v3 in
      OCaml.VSum ("ExpandedTok", [ v1; v2; v3 ])

let vof_info v_token =
  let bnds = [] in
  let arg = vof_token_origin v_token in
  let bnd = ("token", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

(* todo? could also do via a post processing phase with a OCaml.map_v ? *)
let _current_precision = ref default_dumper_precision

let cmdline_flags_precision () =
  [
    ( "-full_token_info",
      Arg.Unit
        (fun () ->
          _current_precision :=
            { default_dumper_precision with full_info = true };
          Tok.pp_full_token_info := true),
      " print also token information in dumper" );
  ]

let vof_info_adjustable_precision x =
  if !_current_precision.full_info then vof_info x
  else if !_current_precision.token_info then
    OCaml.VDict
      [
        ("line", OCaml.vof_int (Tok.line_of_tok x));
        ("col", OCaml.vof_int (Tok.col_of_tok x));
      ]
  else OCaml.VUnit

(* end of meta_parse_info.ml *)

(* When true, recurse into `Sym` svalues when printing. This is fairly likely to
 * blow up into large output, and may even lead to a stack overflow. Use only
 * for debugging, and use caution. *)
let debug_print_sym = false
let vof_tok v = vof_info_adjustable_precision v

(* generated by ocamltarzan with: camlp4o -o /tmp/yyy.ml -I pa/ pa_type_conv.cmo pa_vof.cmo  pr_o.cmo /tmp/xxx.ml  *)

let vof_wrap _of_a (v1, v2) =
  let v1 = _of_a v1 and v2 = vof_tok v2 in
  OCaml.VTuple [ v1; v2 ]

let vof_bracket of_a (t1, x, t2) =
  let v1 = vof_tok t1 in
  let v2 = vof_tok t2 in
  let v = of_a x in
  match v1 with
  | OCaml.VUnit -> v
  | __else__ -> OCaml.VTuple [ v1; v; v2 ]

let vof_ident v = vof_wrap OCaml.vof_string v
let vof_todo_kind v = vof_wrap OCaml.vof_string v
let vof_dotted_name v = OCaml.vof_list vof_ident v

let vof_module_name = function
  | FileName v1 ->
      let v1 = vof_wrap OCaml.vof_string v1 in
      OCaml.VSum ("FileName", [ v1 ])
  | DottedName v1 ->
      let v1 = vof_dotted_name v1 in
      OCaml.VSum ("DottedName", [ v1 ])

let vof_dotted_ident = vof_dotted_name

let rec vof_resolved_name (v1, v2) =
  let v1 = vof_resolved_name_kind v1 in
  let v2 = OCaml.vof_int (SId.to_int v2) in
  OCaml.VTuple [ v1; v2 ]

and vof_canonical_name v1 = OCaml.vof_list OCaml.vof_string v1

and vof_resolved_name_kind = function
  | LocalVar -> OCaml.VSum ("LocalVar", [])
  | Parameter -> OCaml.VSum ("Parameter", [])
  | EnclosedVar -> OCaml.VSum ("EnclosedVar", [])
  | Global -> OCaml.VSum ("Global", [])
  | ImportedEntity v1 ->
      let v1 = vof_canonical_name v1 in
      OCaml.VSum ("ImportedEntity", [ v1 ])
  | ImportedModule v1 ->
      let v1 = vof_canonical_name v1 in
      OCaml.VSum ("ImportedModule", [ v1 ])
  | Macro -> OCaml.VSum ("Macro", [])
  | EnumConstant -> OCaml.VSum ("EnumConstant", [])
  | TypeName -> OCaml.VSum ("TypeName", [])
  | GlobalName (v1, v2) ->
      let v1 = vof_canonical_name v1 in
      let v2 = OCaml.vof_list vof_canonical_name v2 in
      OCaml.VSum ("GlobalName", [ v1; v2 ])

let rec vof_qualifier = function
  | QDots v1 ->
      let v1 = OCaml.vof_list vof_ident_and_targs_opt v1 in
      OCaml.VSum ("QDots", [ v1 ])
  | QExpr (v1, v2) ->
      let v1 = vof_expr v1 in
      let v2 = vof_tok v2 in
      OCaml.VSum ("QExpr", [ v1; v2 ])

and vof_ident_and_targs_opt (v1, v2) =
  let v1 = vof_ident v1 in
  let v2 = OCaml.vof_option vof_type_arguments v2 in
  OCaml.VTuple [ v1; v2 ]

and vof_name_info
    {
      name_middle = v_name_qualifier;
      name_top = v_top;
      name_last = v1;
      name_info = v2;
    } =
  let bnds = [] in
  let arg = vof_id_info v2 in
  let bnd = ("name_info", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_option vof_qualifier v_name_qualifier in
  let bnd = ("name_middle", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_option vof_tok v_top in
  let bnd = ("name_top", arg) in
  let bnds = bnd :: bnds in
  let arg = vof_ident_and_targs_opt v1 in
  let bnd = ("name_last", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

and vof_id_info
    {
      id_resolved = v_id_resolved;
      id_resolved_alternatives = v_id_resolved_alts;
      id_type = v_id_type;
      id_svalue = v3;
      id_flags;
      id_info_id;
    } =
  let bnds = [] in
  let arg = OCaml.vof_ref (OCaml.vof_option vof_svalue) v3 in
  let bnd = ("id_svalue", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_ref (OCaml.vof_option vof_type_) v_id_type in
  let bnd = ("id_type", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_ref (OCaml.vof_option vof_resolved_name) v_id_resolved in
  let bnd = ("id_resolved", arg) in
  let bnds = bnd :: bnds in
  let arg =
    OCaml.vof_ref
      (fun alts -> OCaml.vof_list vof_resolved_name alts)
      v_id_resolved_alts
  in
  let bnd = ("id_resolved_alternative", arg) in
  let bnds = bnd :: bnds in
  let arg =
    OCaml.vof_ref
      (fun id_flags -> OCaml.vof_int (IdFlags.to_int id_flags))
      id_flags
  in
  let bnd = ("id_flags", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_int (IdInfoId.to_int id_info_id) in
  let bnd = ("id_info_id", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

and vof_xml
    { xml_kind = v_xml_tag; xml_attrs = v_xml_attrs; xml_body = v_xml_body } =
  let bnds = [] in
  let arg = OCaml.vof_list vof_xml_body v_xml_body in
  let bnd = ("xml_body", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_list vof_xml_attribute v_xml_attrs in
  let bnd = ("xml_attrs", arg) in
  let bnds = bnd :: bnds in
  let arg = vof_xmlkind v_xml_tag in
  let bnd = ("xml_tag", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

and vof_xmlkind = function
  | XmlClassic (v0, name, v2, v3) ->
      let v0 = vof_tok v0 in
      let name = vof_name name in
      let v2 = vof_tok v2 in
      let v3 = vof_tok v3 in
      OCaml.VSum ("XmlClassic", [ v0; name; v2; v3 ])
  | XmlSingleton (v0, name, v2) ->
      let v0 = vof_tok v0 in
      let name = vof_name name in
      let v2 = vof_tok v2 in
      OCaml.VSum ("XmlSingleton", [ v0; name; v2 ])
  | XmlFragment (v1, v2) ->
      let v1 = vof_tok v1 in
      let v2 = vof_tok v2 in
      OCaml.VSum ("XmlFragment", [ v1; v2 ])

and vof_xml_attribute = function
  | XmlAttr (v1, t, v2) ->
      let v1 = vof_ident v1 and t = vof_tok t and v2 = vof_xml_attr v2 in
      OCaml.VSum ("XmlAttr", [ v1; t; v2 ])
  | XmlAttrExpr v1 ->
      let v1 = vof_bracket vof_expr v1 in
      OCaml.VSum ("XmlAttrExpr", [ v1 ])
  | XmlEllipsis v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("XmlEllipsis", [ v1 ])

and vof_xml_attr v = vof_expr v

and vof_xml_body = function
  | XmlText v1 ->
      let v1 = vof_wrap OCaml.vof_string v1 in
      OCaml.VSum ("XmlText", [ v1 ])
  | XmlExpr v1 ->
      let v1 = vof_bracket (OCaml.vof_option vof_expr) v1 in
      OCaml.VSum ("XmlExpr", [ v1 ])
  | XmlXml v1 ->
      let v1 = vof_xml v1 in
      OCaml.VSum ("XmlXml", [ v1 ])

and vof_name = function
  | Id (v1, v2) ->
      let v1 = vof_ident v1 and v2 = vof_id_info v2 in
      OCaml.VSum ("Id", [ v1; v2 ])
  | IdQualified v1 ->
      let v1 = vof_name_info v1 in
      OCaml.VSum ("IdQualified", [ v1 ])

and vof_expr e =
  (* TODO: also dump e_id? *)
  match e.e with
  | LocalImportAll (v1, v2, v3) ->
      let v1 = vof_module_name v1 in
      let v2 = vof_tok v2 in
      let v3 = vof_expr v3 in
      OCaml.VSum ("LocalImportAll", [ v1; v2; v3 ])
  | DotAccessEllipsis (v1, v2) ->
      let v1 = vof_expr v1 in
      let v2 = vof_tok v2 in
      OCaml.VSum ("DotAccessEllipsis", [ v1; v2 ])
  | DisjExpr (v1, v2) ->
      let v1 = vof_expr v1 in
      let v2 = vof_expr v2 in
      OCaml.VSum ("DisjExpr", [ v1; v2 ])
  | Xml v1 ->
      let v1 = vof_xml v1 in
      OCaml.VSum ("Xml", [ v1 ])
  | L v1 ->
      let v1 = vof_literal v1 in
      OCaml.VSum ("L", [ v1 ])
  | Container (v1, v2) ->
      let v1 = vof_container_operator v1
      and v2 = vof_bracket (OCaml.vof_list vof_expr) v2 in
      OCaml.VSum ("Container", [ v1; v2 ])
  | Comprehension (v1, v2) ->
      let v1 = vof_container_operator v1
      and v2 = vof_bracket vof_comprehension v2 in
      OCaml.VSum ("Comprehension", [ v1; v2 ])
  | Record v1 ->
      let v1 = vof_bracket (OCaml.vof_list vof_field) v1 in
      OCaml.VSum ("Record", [ v1 ])
  | Constructor (v1, v2) ->
      let v1 = vof_name v1 and v2 = vof_bracket (OCaml.vof_list vof_expr) v2 in
      OCaml.VSum ("Constructor", [ v1; v2 ])
  | RegexpTemplate (v1, v2) ->
      let v1 = vof_bracket vof_expr v1 in
      let v2 = OCaml.vof_option (vof_wrap OCaml.vof_string) v2 in
      OCaml.VSum ("RegexpTemplate", [ v1; v2 ])
  | Lambda v1 ->
      let v1 = vof_function_definition v1 in
      OCaml.VSum ("Lambda", [ v1 ])
  | AnonClass v1 ->
      let v1 = vof_class_definition v1 in
      OCaml.VSum ("AnonClass", [ v1 ])
  | N v1 ->
      let v1 = vof_name v1 in
      OCaml.VSum ("N", [ v1 ])
  | IdSpecial v1 ->
      let v1 = vof_wrap vof_special v1 in
      OCaml.VSum ("IdSpecial", [ v1 ])
  | Call (v1, v2) ->
      let v1 = vof_expr v1 and v2 = vof_arguments v2 in
      OCaml.VSum ("Call", [ v1; v2 ])
  | New (v0, v1, v2, v3) ->
      let v0 = vof_tok v0 in
      let v1 = vof_type_ v1 and v2 = vof_id_info v2 and v3 = vof_arguments v3 in
      OCaml.VSum ("New", [ v0; v1; v2; v3 ])
  | Assign (v1, v2, v3) ->
      let v1 = vof_expr v1 and v2 = vof_tok v2 and v3 = vof_expr v3 in
      OCaml.VSum ("Assign", [ v1; v2; v3 ])
  | AssignOp (v1, v2, v3) ->
      let v1 = vof_expr v1
      and v2 = vof_wrap vof_arithmetic_operator v2
      and v3 = vof_expr v3 in
      OCaml.VSum ("AssignOp", [ v1; v2; v3 ])
  | LetPattern (v1, v2) ->
      let v1 = vof_pattern v1 and v2 = vof_expr v2 in
      OCaml.VSum ("LetPattern", [ v1; v2 ])
  | DotAccess (v1, t, v2) ->
      let v1 = vof_expr v1 and t = vof_tok t and v2 = vof_field_name v2 in
      OCaml.VSum ("DotAccess", [ v1; t; v2 ])
  | ArrayAccess (v1, v2) ->
      let v1 = vof_expr v1 and v2 = vof_bracket vof_expr v2 in
      OCaml.VSum ("ArrayAccess", [ v1; v2 ])
  | SliceAccess (v1, v2) ->
      let f = OCaml.vof_option vof_expr in
      let v1 = vof_expr v1 and v2 = vof_bracket (OCaml.vof_all3 f f f) v2 in
      OCaml.VSum ("SliceAccess", [ v1; v2 ])
  | Conditional (v1, v2, v3) ->
      let v1 = vof_expr v1 and v2 = vof_expr v2 and v3 = vof_expr v3 in
      OCaml.VSum ("Conditional", [ v1; v2; v3 ])
  | Yield (t, v1, v2) ->
      let t = vof_tok t in
      let v1 = OCaml.vof_option vof_expr v1 and v2 = OCaml.vof_bool v2 in
      OCaml.VSum ("Yield", [ t; v1; v2 ])
  | Await (t, v1) ->
      let t = vof_tok t in
      let v1 = vof_expr v1 in
      OCaml.VSum ("Await", [ t; v1 ])
  | Cast (v1, t, v2) ->
      let v1 = vof_type_ v1 and t = vof_tok t and v2 = vof_expr v2 in
      OCaml.VSum ("Cast", [ v1; t; v2 ])
  | Seq v1 ->
      let v1 = OCaml.vof_list vof_expr v1 in
      OCaml.VSum ("Seq", [ v1 ])
  | Ref (t, v1) ->
      let t = vof_tok t in
      let v1 = vof_expr v1 in
      OCaml.VSum ("Ref", [ t; v1 ])
  | DeRef (t, v1) ->
      let t = vof_tok t in
      let v1 = vof_expr v1 in
      OCaml.VSum ("DeRef", [ t; v1 ])
  | Alias (alias, v1) ->
      let alias = vof_wrap OCaml.vof_string alias in
      let v1 = vof_expr v1 in
      OCaml.VSum ("Alias", [ alias; v1 ])
  | Ellipsis v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("Ellipsis", [ v1 ])
  | DeepEllipsis v1 ->
      let v1 = vof_bracket vof_expr v1 in
      OCaml.VSum ("DeepEllipsis", [ v1 ])
  | TypedMetavar (v1, v2, v3) ->
      let v1 = vof_ident v1 and v2 = vof_tok v2 and v3 = vof_type_ v3 in
      OCaml.VSum ("TypedMetavar", [ v1; v2; v3 ])
  | StmtExpr v1 ->
      let v1 = vof_stmt v1 in
      OCaml.VSum ("StmtExpr", [ v1 ])
  | OtherExpr (v1, v2) ->
      let v1 = vof_todo_kind v1 and v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("OtherExpr", [ v1; v2 ])
  | RawExpr x ->
      let x = vof_raw_tree x in
      OCaml.VSum ("RawExpr", [ x ])

and vof_field_name = function
  | FN v1 ->
      let v1 = vof_name v1 in
      OCaml.VSum ("FN", [ v1 ])
  | FDynamic v1 ->
      let v1 = vof_expr v1 in
      OCaml.VSum ("FDynamic", [ v1 ])

and vof_entity_name = function
  | EN v1 ->
      let v1 = vof_name v1 in
      OCaml.VSum ("EN", [ v1 ])
  | EDynamic v1 ->
      let v1 = vof_expr v1 in
      OCaml.VSum ("EDynamic", [ v1 ])
  | EPattern v1 ->
      let v1 = vof_pattern v1 in
      OCaml.VSum ("EPattern", [ v1 ])
  | OtherEntity (v1, v2) ->
      let v1 = vof_todo_kind v1 and v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("OtherEntity", [ v1; v2 ])

and vof_literal = function
  | Unit v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("Unit", [ v1 ])
  | Bool v1 ->
      let v1 = vof_wrap OCaml.vof_bool v1 in
      OCaml.VSum ("Bool", [ v1 ])
  | Int (opt, tk) ->
      let v1 = vof_wrap (OCaml.vof_option OCaml.vof_int64) (opt, tk) in
      OCaml.VSum ("Int", [ v1 ])
  | Float v1 ->
      let v1 = vof_wrap (OCaml.vof_option OCaml.vof_float) v1 in
      OCaml.VSum ("Float", [ v1 ])
  | Imag v1 ->
      let v1 = vof_wrap OCaml.vof_string v1 in
      OCaml.VSum ("Imag", [ v1 ])
  | Ratio v1 ->
      let v1 = vof_wrap OCaml.vof_string v1 in
      OCaml.VSum ("Ratio", [ v1 ])
  | Atom (v0, v1) ->
      let v0 = vof_tok v0 in
      let v1 = vof_wrap OCaml.vof_string v1 in
      OCaml.VSum ("Atom", [ v0; v1 ])
  | Char v1 ->
      let v1 = vof_wrap OCaml.vof_string v1 in
      OCaml.VSum ("Char", [ v1 ])
  | String v1 ->
      let v1 = vof_bracket (vof_wrap OCaml.vof_string) v1 in
      OCaml.VSum ("String", [ v1 ])
  | Regexp (v1, v2) ->
      let v1 = vof_bracket (vof_wrap OCaml.vof_string) v1 in
      let v2 = OCaml.vof_option (vof_wrap OCaml.vof_string) v2 in
      OCaml.VSum ("Regexp", [ v1; v2 ])
  | Null v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("Null", [ v1 ])
  | Undefined v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("Undefined", [ v1 ])

and vof_const_type = function
  | Cbool -> OCaml.VSum ("Cbool", [])
  | Cint -> OCaml.VSum ("Cint", [])
  | Cstr -> OCaml.VSum ("Cstr", [])
  | Cany -> OCaml.VSum ("Cany", [])

and vof_svalue = function
  | Lit v1 ->
      let v1 = vof_literal v1 in
      OCaml.VSum ("Lit", [ v1 ])
  | Cst v1 ->
      let v1 = vof_const_type v1 in
      OCaml.VSum ("Cst", [ v1 ])
  | Sym v1 -> vof_sym v1
  | NotCst -> OCaml.VSum ("NotCst", [])

and vof_sym v1 =
  (* Do NOT go into symbolic values in production, see "CAREFUL" note in
   * AST_generic.svalue. *)
  let lst =
    if debug_print_sym then
      let v1 = vof_expr v1 in
      [ v1 ]
    else []
  in
  OCaml.VSum ("Sym", lst)

and vof_container_operator = function
  | Array -> OCaml.VSum ("Array", [])
  | List -> OCaml.VSum ("List", [])
  | Set -> OCaml.VSum ("Set", [])
  | Dict -> OCaml.VSum ("Dict", [])
  | Tuple -> OCaml.VSum ("Tuple", [])

and vof_comprehension (v1, v2) =
  let v1 = vof_expr v1 in
  let v2 = OCaml.vof_list vof_for_or_if_comp v2 in
  OCaml.VTuple [ v1; v2 ]

and vof_for_or_if_comp = function
  | CompFor (v1, v2, v3, v4) ->
      let v1 = vof_tok v1 in
      let v2 = vof_pattern v2 in
      let v3 = vof_tok v3 in
      let v4 = vof_expr v4 in
      OCaml.VSum ("CompFor", [ v1; v2; v3; v4 ])
  | CompIf (v1, v2) ->
      let v1 = vof_tok v1 in
      let v2 = vof_expr v2 in
      OCaml.VSum ("CompIf", [ v1; v2 ])

and vof_special = function
  | ForOf -> OCaml.VSum ("ForOf", [])
  | Defined -> OCaml.VSum ("Defined", [])
  | This -> OCaml.VSum ("This", [])
  | Super -> OCaml.VSum ("Super", [])
  | Self -> OCaml.VSum ("Self", [])
  | Parent -> OCaml.VSum ("Parent", [])
  | Eval -> OCaml.VSum ("Eval", [])
  | Typeof -> OCaml.VSum ("Typeof", [])
  | Instanceof -> OCaml.VSum ("Instanceof", [])
  | Sizeof -> OCaml.VSum ("Sizeof", [])
  | ConcatString v1 ->
      let v1 = vof_interpolated_kind v1 in
      OCaml.VSum ("ConcatString", [ v1 ])
  | Spread -> OCaml.VSum ("Spread", [])
  | InterpolatedElement -> OCaml.VSum ("InterpolatedElement", [])
  | HashSplat -> OCaml.VSum ("HashSplat", [])
  | EncodedString v1 ->
      let v1 = OCaml.vof_string v1 in
      OCaml.VSum ("EncodedString", [ v1 ])
  | Op v1 ->
      let v1 = vof_arithmetic_operator v1 in
      OCaml.VSum ("Op", [ v1 ])
  | IncrDecr v ->
      let v = vof_inc_dec v in
      OCaml.VSum ("IncrDecr", [ v ])
  | NextArrayIndex -> OCaml.VSum ("NextArrayIndex", [])
  | Require -> OCaml.VSum ("Require", [])

and vof_interpolated_kind = function
  | FString v1 ->
      let v1 = OCaml.vof_string v1 in
      OCaml.VSum ("FString", [ v1 ])
  | InterpolatedConcat -> OCaml.VSum ("InterpolatedConcat", [])
  | SequenceConcat -> OCaml.VSum ("SequenceConcat", [])
  | TaggedTemplateLiteral -> OCaml.VSum ("TaggedTemplateLiteral", [])

and vof_inc_dec (v1, v2) =
  let v1 = vof_incr_decr v1 and v2 = vof_prepost v2 in
  OCaml.VTuple [ v1; v2 ]

and vof_incr_decr = function
  | Incr -> OCaml.VSum ("Incr", [])
  | Decr -> OCaml.VSum ("Decr", [])

and vof_prepost = function
  | Prefix -> OCaml.VSum ("Prefix", [])
  | Postfix -> OCaml.VSum ("Postfix", [])

and vof_arithmetic_operator = function
  | NotIs -> OCaml.VSum ("NotIs", [])
  | Is -> OCaml.VSum ("Is", [])
  | NotIn -> OCaml.VSum ("NotIn", [])
  | In -> OCaml.VSum ("In", [])
  | Elvis -> OCaml.VSum ("Elvis", [])
  | NotNullPostfix -> OCaml.VSum ("NotNullPostfix", [])
  | Nullish -> OCaml.VSum ("Nullish", [])
  | Range -> OCaml.VSum ("Range", [])
  | RangeInclusive -> OCaml.VSum ("RangeInclusive", [])
  | RegexpMatch -> OCaml.VSum ("RegexpMatch", [])
  | NotMatch -> OCaml.VSum ("NotMatch", [])
  | Concat -> OCaml.VSum ("Concat", [])
  | Append -> OCaml.VSum ("Append", [])
  | Plus -> OCaml.VSum ("Plus", [])
  | Minus -> OCaml.VSum ("Minus", [])
  | Mult -> OCaml.VSum ("Mult", [])
  | Div -> OCaml.VSum ("Div", [])
  | Mod -> OCaml.VSum ("Mod", [])
  | Pow -> OCaml.VSum ("Pow", [])
  | FloorDiv -> OCaml.VSum ("FloorDiv", [])
  | MatMult -> OCaml.VSum ("MatMult", [])
  | LSL -> OCaml.VSum ("LSL", [])
  | LSR -> OCaml.VSum ("LSR", [])
  | ASR -> OCaml.VSum ("ASR", [])
  | BitOr -> OCaml.VSum ("BitOr", [])
  | BitXor -> OCaml.VSum ("BitXor", [])
  | BitAnd -> OCaml.VSum ("BitAnd", [])
  | BitNot -> OCaml.VSum ("BitNot", [])
  | BitClear -> OCaml.VSum ("BitClear", [])
  | And -> OCaml.VSum ("And", [])
  | Or -> OCaml.VSum ("Or", [])
  | Not -> OCaml.VSum ("Not", [])
  | Xor -> OCaml.VSum ("Xor", [])
  | Pipe -> OCaml.VSum ("Pipe", [])
  | Eq -> OCaml.VSum ("Eq", [])
  | NotEq -> OCaml.VSum ("NotEq", [])
  | PhysEq -> OCaml.VSum ("PhysEq", [])
  | NotPhysEq -> OCaml.VSum ("NotPhysEq", [])
  | Lt -> OCaml.VSum ("Lt", [])
  | LtE -> OCaml.VSum ("LtE", [])
  | Gt -> OCaml.VSum ("Gt", [])
  | GtE -> OCaml.VSum ("GtE", [])
  | Cmp -> OCaml.VSum ("Cmp", [])
  | Length -> OCaml.VSum ("Length", [])
  | Background -> OCaml.VSum ("Background", [])
  | LDA -> OCaml.VSum ("LDA", [])
  | RDA -> OCaml.VSum ("RDA", [])
  | LSA -> OCaml.VSum ("LSA", [])
  | RSA -> OCaml.VSum ("RSA", [])

and vof_arguments v = vof_bracket (OCaml.vof_list vof_argument) v

and vof_argument = function
  | Arg v1 ->
      let v1 = vof_expr v1 in
      OCaml.VSum ("Arg", [ v1 ])
  | ArgKwd (v1, v2) ->
      let v1 = vof_ident v1 and v2 = vof_expr v2 in
      OCaml.VSum ("ArgKwd", [ v1; v2 ])
  | ArgKwdOptional (v1, v2) ->
      let v1 = vof_ident v1 and v2 = vof_expr v2 in
      OCaml.VSum ("ArgKwdOptional", [ v1; v2 ])
  | ArgType v1 ->
      let v1 = vof_type_ v1 in
      OCaml.VSum ("ArgType", [ v1 ])
  | OtherArg (v1, v2) ->
      let v1 = vof_todo_kind v1 and v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("OtherArg", [ v1; v2 ])

and vof_type_ { t; t_attrs } =
  let bnds = [] in
  let arg = vof_type_kind t in
  let bnd = ("t", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_list vof_attribute t_attrs in
  let bnd = ("t_attrs", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

and vof_type_kind = function
  | TyEllipsis v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("TyEllipsis", [ v1 ])
  | TyRecordAnon (v0, v1) ->
      let v0 = vof_class_kind v0 in
      let v1 = vof_bracket (OCaml.vof_list vof_field) v1 in
      OCaml.VSum ("TyRecordAnon", [ v0; v1 ])
  | TyOr (v1, v2, v3) ->
      let v1 = vof_type_ v1 in
      let v2 = vof_tok v2 in
      let v3 = vof_type_ v3 in
      OCaml.VSum ("TyOr", [ v1; v2; v3 ])
  | TyAnd (v1, v2, v3) ->
      let v1 = vof_type_ v1 in
      let v2 = vof_tok v2 in
      let v3 = vof_type_ v3 in
      OCaml.VSum ("TyAnd", [ v1; v2; v3 ])
  | TyFun (v1, v2) ->
      let v1 = OCaml.vof_list vof_parameter v1 and v2 = vof_type_ v2 in
      OCaml.VSum ("TyFun", [ v1; v2 ])
  | TyApply (v1, v2) ->
      let v1 = vof_type_ v1 and v2 = vof_type_arguments v2 in
      OCaml.VSum ("TyApply", [ v1; v2 ])
  | TyN v1 ->
      let v1 = vof_name v1 in
      OCaml.VSum ("TyN", [ v1 ])
  | TyVar v1 ->
      let v1 = vof_ident v1 in
      OCaml.VSum ("TyVar", [ v1 ])
  | TyAny v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("TyAny", [ v1 ])
  | TyArray (v1, v2) ->
      let v1 = vof_bracket (OCaml.vof_option vof_expr) v1
      and v2 = vof_type_ v2 in
      OCaml.VSum ("TyArray", [ v1; v2 ])
  | TyPointer (t, v1) ->
      let t = vof_tok t in
      let v1 = vof_type_ v1 in
      OCaml.VSum ("TyPointer", [ t; v1 ])
  | TyRef (t, v1) ->
      let t = vof_tok t in
      let v1 = vof_type_ v1 in
      OCaml.VSum ("TyRef", [ t; v1 ])
  | TyTuple v1 ->
      let v1 = vof_bracket (OCaml.vof_list vof_type_) v1 in
      OCaml.VSum ("TyTuple", [ v1 ])
  | TyQuestion (v1, t) ->
      let v1 = vof_type_ v1 in
      let t = vof_tok t in
      OCaml.VSum ("TyQuestion", [ t; v1 ])
  | TyRest (t, v1) ->
      let t = vof_tok t in
      let v1 = vof_type_ v1 in
      OCaml.VSum ("TyRest", [ v1; t ])
  | TyExpr v1 ->
      let v1 = vof_expr v1 in
      OCaml.VSum ("TyExpr", [ v1 ])
  | OtherType (v1, v2) ->
      let v1 = vof_todo_kind v1 in
      let v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("OtherType", [ v1; v2 ])

and vof_type_arguments v = vof_bracket (OCaml.vof_list vof_type_argument) v

and vof_type_argument = function
  | TA v1 ->
      let v1 = vof_type_ v1 in
      OCaml.VSum ("TA", [ v1 ])
  | TAWildcard (v1, v2) ->
      let v1 = vof_tok v1 in
      let v2 =
        OCaml.vof_option
          (fun (v1, v2) ->
            let v1 = vof_wrap OCaml.vof_bool v1 in
            let v2 = vof_type_ v2 in
            OCaml.VTuple [ v1; v2 ])
          v2
      in
      OCaml.VSum ("AWildcard", [ v1; v2 ])
  | TAExpr v1 ->
      let v1 = vof_expr v1 in
      OCaml.VSum ("TAExpr", [ v1 ])
  | OtherTypeArg (v1, v2) ->
      let v1 = vof_todo_kind v1 and v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("OtherTypeArg", [ v1; v2 ])

and vof_keyword_attribute = function
  | SealedClass -> OCaml.VSum ("SealedClass", [])
  | AnnotationClass -> OCaml.VSum ("AnnotationClass", [])
  | RecordClass -> OCaml.VSum ("RecordClass", [])
  | EnumClass -> OCaml.VSum ("EnumClass", [])
  | Lazy -> OCaml.VSum ("Lazy", [])
  | Static -> OCaml.VSum ("Static", [])
  | Volatile -> OCaml.VSum ("Volatile", [])
  | Extern -> OCaml.VSum ("Extern", [])
  | Public -> OCaml.VSum ("Public", [])
  | Private -> OCaml.VSum ("Private", [])
  | Protected -> OCaml.VSum ("Protected", [])
  | Abstract -> OCaml.VSum ("Abstract", [])
  | Final -> OCaml.VSum ("Final", [])
  | Override -> OCaml.VSum ("Override", [])
  | Var -> OCaml.VSum ("Var", [])
  | Let -> OCaml.VSum ("Let", [])
  | Const -> OCaml.VSum ("Const", [])
  | Mutable -> OCaml.VSum ("Mutable", [])
  | Generator -> OCaml.VSum ("Generator", [])
  | Async -> OCaml.VSum ("Async", [])
  | Recursive -> OCaml.VSum ("Recursive", [])
  | MutuallyRecursive -> OCaml.VSum ("MutuallyRecursive", [])
  | Inline -> OCaml.VSum ("Inline", [])
  | Ctor -> OCaml.VSum ("Ctor", [])
  | Dtor -> OCaml.VSum ("Dtor", [])
  | Getter -> OCaml.VSum ("Getter", [])
  | Setter -> OCaml.VSum ("Setter", [])
  | Optional -> OCaml.VSum ("Optional", [])
  | NotNull -> OCaml.VSum ("NotNull", [])
  | Unsafe -> OCaml.VSum ("Unsafe", [])
  | DefaultImpl -> OCaml.VSum ("DefaultImpl", [])
  | Throws -> OCaml.VSum ("Throws", [])
  | Rethrows -> OCaml.VSum ("Rethrows", [])

and vof_attribute = function
  | KeywordAttr x ->
      let v1 = vof_wrap vof_keyword_attribute x in
      OCaml.VSum ("KeywordAttr", [ v1 ])
  | NamedAttr (t, v1, v3) ->
      let t = vof_tok t in
      let v1 = vof_name v1
      and v3 = vof_bracket (OCaml.vof_list vof_argument) v3 in
      OCaml.VSum ("NamedAttr", [ t; v1; v3 ])
  | OtherAttribute (v1, v2) ->
      let v1 = vof_todo_kind v1 and v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("OtherAttribute", [ v1; v2 ])

and vof_stmt st =
  (* todo: dump also the s_id? *)
  match st.s with
  | DisjStmt (v1, v2) ->
      let v1 = vof_stmt v1 in
      let v2 = vof_stmt v2 in
      OCaml.VSum ("DisjStmt", [ v1; v2 ])
  | ExprStmt (v1, t) ->
      let v1 = vof_expr v1 in
      let t = vof_tok t in
      OCaml.VSum ("ExprStmt", [ v1; t ])
  | DefStmt v1 ->
      let v1 = vof_definition v1 in
      OCaml.VSum ("DefStmt", [ v1 ])
  | DirectiveStmt v1 ->
      let v1 = vof_directive v1 in
      OCaml.VSum ("DirectiveStmt", [ v1 ])
  | Block v1 ->
      let v1 = vof_bracket (OCaml.vof_list vof_stmt) v1 in
      OCaml.VSum ("Block", [ v1 ])
  | If (t, v1, v2, v3) ->
      let t = vof_tok t in
      let v1 = vof_condition v1
      and v2 = vof_stmt v2
      and v3 = OCaml.vof_option vof_stmt v3 in
      OCaml.VSum ("If", [ t; v1; v2; v3 ])
  | While (t, v1, v2) ->
      let t = vof_tok t in
      let v1 = vof_condition v1 and v2 = vof_stmt v2 in
      OCaml.VSum ("While", [ t; v1; v2 ])
  | DoWhile (t, v1, v2) ->
      let t = vof_tok t in
      let v1 = vof_stmt v1 and v2 = vof_expr v2 in
      OCaml.VSum ("DoWhile", [ t; v1; v2 ])
  | For (t, v1, v2) ->
      let t = vof_tok t in
      let v1 = vof_for_header v1 and v2 = vof_stmt v2 in
      OCaml.VSum ("For", [ t; v1; v2 ])
  | Switch (v0, v1, v2) ->
      let v0 = vof_tok v0 in
      let v1 = OCaml.vof_option vof_condition v1
      and v2 = OCaml.vof_list vof_case_and_body v2 in
      OCaml.VSum ("Switch", [ v0; v1; v2 ])
  | Return (t, v1, sc) ->
      let t = vof_tok t in
      let v1 = OCaml.vof_option vof_expr v1 in
      let sc = vof_tok sc in
      OCaml.VSum ("Return", [ t; v1; sc ])
  | Continue (t, v1, sc) ->
      let t = vof_tok t in
      let v1 = vof_label_ident v1 in
      let sc = vof_tok sc in
      OCaml.VSum ("Continue", [ t; v1; sc ])
  | Break (t, v1, sc) ->
      let t = vof_tok t in
      let v1 = vof_label_ident v1 in
      let sc = vof_tok sc in
      OCaml.VSum ("Break", [ t; v1; sc ])
  | Label (v1, v2) ->
      let v1 = vof_label v1 and v2 = vof_stmt v2 in
      OCaml.VSum ("Label", [ v1; v2 ])
  | Goto (t, v1, sc) ->
      let t = vof_tok t in
      let v1 = vof_label v1 in
      let sc = vof_tok sc in
      OCaml.VSum ("Goto", [ t; v1; sc ])
  | Throw (t, v1, sc) ->
      let t = vof_tok t in
      let v1 = vof_expr v1 in
      let sc = vof_tok sc in
      OCaml.VSum ("Throw", [ t; v1; sc ])
  | Try (t, v1, v2, v3, v4) ->
      let t = vof_tok t in
      let v1 = vof_stmt v1
      and v2 = OCaml.vof_list vof_catch v2
      and v3 = OCaml.vof_option vof_try_else v3
      and v4 = OCaml.vof_option vof_finally v4 in
      OCaml.VSum ("Try", [ t; v1; v2; v3; v4 ])
  | WithUsingResource (t, v1, v2) ->
      let t = vof_tok t in
      let v1 = OCaml.vof_list vof_stmt v1 in
      let v2 = vof_stmt v2 in
      OCaml.VSum ("WithUsingResource", [ t; v1; v2 ])
  | Assert (t, args, sc) ->
      let t = vof_tok t in
      let args = vof_arguments args in
      let sc = vof_tok sc in
      OCaml.VSum ("Assert", [ t; args; sc ])
  | OtherStmtWithStmt (v1, v2, v3) ->
      let v1 = vof_other_stmt_with_stmt_operator v1
      and v2 = OCaml.vof_list vof_any v2
      and v3 = vof_stmt v3 in
      OCaml.VSum ("OtherStmtWithStmt", [ v1; v2; v3 ])
  | OtherStmt (v1, v2) ->
      let v1 = vof_other_stmt_operator v1 and v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("OtherStmt", [ v1; v2 ])
  | RawStmt x ->
      let x = vof_raw_tree x in
      OCaml.VSum ("RawStmt", [ x ])

and vof_condition = function
  | Cond v1 ->
      let v1 = vof_expr v1 in
      OCaml.VSum ("Cond", [ v1 ])
  | OtherCond (v1, v2) ->
      let v1 = vof_todo_kind v1 and v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("OtherCond", [ v1; v2 ])

and vof_other_stmt_with_stmt_operator = function
  | OSWS_Block v1 ->
      let v1 = vof_todo_kind v1 in
      OCaml.VSum ("OSWS_Block", [ v1 ])
  | OSWS_With -> OCaml.VSum ("OSWS_With", [])
  | OSWS_Else_in_try -> OCaml.VSum ("OSWS_Else_in_try", [])
  | OSWS_Iterator -> OCaml.VSum ("OSWS_Iterator", [])
  | OSWS_SEH -> OCaml.VSum ("OSWS_SEH", [])
  | OSWS_Todo -> OCaml.VSum ("OSWS_Todo", [])

and vof_label_ident = function
  | LNone -> OCaml.VSum ("LNone", [])
  | LId v1 ->
      let v1 = vof_label v1 in
      OCaml.VSum ("LId", [ v1 ])
  | LInt v1 ->
      let v1 = vof_wrap OCaml.vof_int v1 in
      OCaml.VSum ("LInt", [ v1 ])
  | LDynamic v1 ->
      let v1 = vof_expr v1 in
      OCaml.VSum ("LDynamic", [ v1 ])

and vof_case_and_body = function
  | CasesAndBody (v1, v2) ->
      let v1 = OCaml.vof_list vof_case v1 and v2 = vof_stmt v2 in
      OCaml.VSum ("CasesAndBody", [ v1; v2 ])
  | CaseEllipsis v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("CaseEllipsis", [ v1 ])

and vof_case = function
  | OtherCase (v1, v2) ->
      let v1 = vof_todo_kind v1 in
      let v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("OtherCase", [ v1; v2 ])
  | Case (t, v1) ->
      let t = vof_tok t in
      let v1 = vof_pattern v1 in
      OCaml.VSum ("Case", [ t; v1 ])
  | CaseEqualExpr (v1, v2) ->
      let v1 = vof_tok v1 in
      let v2 = vof_expr v2 in
      OCaml.VSum ("CaseEqualExpr", [ v1; v2 ])
  | Default t ->
      let t = vof_tok t in
      OCaml.VSum ("Default", [ t ])

and vof_catch (t, v1, v2) =
  let t = vof_tok t in
  let v1 = vof_catch_exn v1 and v2 = vof_stmt v2 in
  OCaml.VTuple [ t; v1; v2 ]

and vof_catch_exn = function
  | OtherCatch (v1, v2) ->
      let v1 = vof_todo_kind v1 in
      let v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("OtherCatch", [ v1; v2 ])
  | CatchPattern v ->
      let v = vof_pattern v in
      OCaml.VSum ("CatchPattern", [ v ])
  | CatchParam v1 ->
      let v1 = vof_parameter_classic v1 in
      OCaml.VSum ("CatchParam", [ v1 ])

and vof_try_else v = vof_tok_and_stmt v
and vof_finally v = vof_tok_and_stmt v

and vof_tok_and_stmt (t, v) =
  let t = vof_tok t in
  let v = vof_stmt v in
  OCaml.VTuple [ t; v ]

and vof_label v = vof_ident v

and vof_for_header = function
  | ForClassic (v1, v2, v3) ->
      let v1 = OCaml.vof_list vof_for_var_or_expr v1
      and v2 = OCaml.vof_option vof_expr v2
      and v3 = OCaml.vof_option vof_expr v3 in
      OCaml.VSum ("ForClassic", [ v1; v2; v3 ])
  | ForEach v1 ->
      let v1 = vof_for_each v1 in
      OCaml.VSum ("ForEach", [ v1 ])
  | MultiForEach v1 ->
      let v1 = OCaml.vof_list vof_multi_for_each v1 in
      OCaml.VSum ("MultiForEach", [ v1 ])
  | ForEllipsis t ->
      let t = vof_tok t in
      OCaml.VSum ("ForEllipsis", [ t ])

and vof_for_each (v1, t, v2) =
  let t = vof_tok t in
  let v1 = vof_pattern v1 and v2 = vof_expr v2 in
  OCaml.VTuple [ v1; t; v2 ]

and vof_multi_for_each = function
  | FE v1 ->
      let v1 = vof_for_each v1 in
      OCaml.VSum ("FE", [ v1 ])
  | FECond (v1, t, v2) ->
      let t = vof_tok t in
      let v1 = vof_for_each v1 and v2 = vof_expr v2 in
      OCaml.VSum ("FECond", [ v1; t; v2 ])
  | FEllipsis t ->
      let t = vof_tok t in
      OCaml.VSum ("FEllipsis", [ t ])

and vof_for_var_or_expr = function
  | ForInitVar (v1, v2) ->
      let v1 = vof_entity v1 and v2 = vof_variable_definition v2 in
      OCaml.VSum ("ForInitVar", [ v1; v2 ])
  | ForInitExpr v1 ->
      let v1 = vof_expr v1 in
      OCaml.VSum ("ForInitExpr", [ v1 ])

and vof_other_stmt_operator = function
  | OS_ExprStmt2 -> OCaml.VSum ("OS_ExprStmt2", [])
  | OS_Redo -> OCaml.VSum ("OS_Redo", [])
  | OS_Retry -> OCaml.VSum ("OS_Retry", [])
  | OS_Todo -> OCaml.VSum ("OS_Todo", [])
  | OS_Delete -> OCaml.VSum ("OS_Delete", [])
  | OS_Async -> OCaml.VSum ("OS_Async", [])
  | OS_ForOrElse -> OCaml.VSum ("OS_ForOrElse", [])
  | OS_WhileOrElse -> OCaml.VSum ("OS_WhileOrElse", [])
  | OS_TryOrElse -> OCaml.VSum ("OS_TryOrElse", [])
  | OS_ThrowFrom -> OCaml.VSum ("OS_ThrowFrom", [])
  | OS_ThrowNothing -> OCaml.VSum ("OS_ThrowNothing", [])
  | OS_ThrowArgsLocation -> OCaml.VSum ("OS_ThrowArgsLocation", [])
  | OS_GlobalComplex -> OCaml.VSum ("OS_GlobalComplex", [])
  | OS_Pass -> OCaml.VSum ("OS_Pass", [])
  | OS_Asm -> OCaml.VSum ("OS_Asm", [])
  | OS_Go -> OCaml.VSum ("OS_Go", [])
  | OS_Defer -> OCaml.VSum ("OS_Defer", [])
  | OS_Extension -> OCaml.VSum ("OS_Extension", [])
  | OS_Fallthrough -> OCaml.VSum ("OS_Fallthrough", [])

and vof_pattern = function
  | PatEllipsis v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("PatEllipsis", [ v1 ])
  | PatId (v1, v2) ->
      let v1 = vof_ident v1 and v2 = vof_id_info v2 in
      OCaml.VSum ("PatId", [ v1; v2 ])
  | PatLiteral v1 ->
      let v1 = vof_literal v1 in
      OCaml.VSum ("PatLiteral", [ v1 ])
  | PatType v1 ->
      let v1 = vof_type_ v1 in
      OCaml.VSum ("PatType", [ v1 ])
  | PatRecord v1 ->
      let v1 =
        vof_bracket
          (OCaml.vof_list (fun (v1, v2) ->
               let v1 = vof_dotted_ident v1 and v2 = vof_pattern v2 in
               OCaml.VTuple [ v1; v2 ]))
          v1
      in
      OCaml.VSum ("PatRecord", [ v1 ])
  | PatConstructor (v1, v2) ->
      let v1 = vof_name v1 and v2 = OCaml.vof_list vof_pattern v2 in
      OCaml.VSum ("PatConstructor", [ v1; v2 ])
  | PatWhen (v1, v2) ->
      let v1 = vof_pattern v1 and v2 = vof_expr v2 in
      OCaml.VSum ("PatWhen", [ v1; v2 ])
  | PatAs (v1, v2) ->
      let v1 = vof_pattern v1
      and v2 =
        match v2 with
        | v1, v2 ->
            let v1 = vof_ident v1 and v2 = vof_id_info v2 in
            OCaml.VTuple [ v1; v2 ]
      in
      OCaml.VSum ("PatAs", [ v1; v2 ])
  | PatTuple v1 ->
      let v1 = vof_bracket (OCaml.vof_list vof_pattern) v1 in
      OCaml.VSum ("PatTuple", [ v1 ])
  | PatList v1 ->
      let v1 = vof_bracket (OCaml.vof_list vof_pattern) v1 in
      OCaml.VSum ("PatList", [ v1 ])
  | PatKeyVal (v1, v2) ->
      let v1 = vof_pattern v1 and v2 = vof_pattern v2 in
      OCaml.VSum ("PatKeyVal", [ v1; v2 ])
  | PatWildcard v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("PatWildcard", [ v1 ])
  | PatDisj (v1, v2) ->
      let v1 = vof_pattern v1 and v2 = vof_pattern v2 in
      OCaml.VSum ("PatDisj", [ v1; v2 ])
  | PatTyped (v1, v2) ->
      let v1 = vof_pattern v1 and v2 = vof_type_ v2 in
      OCaml.VSum ("PatTyped", [ v1; v2 ])
  | DisjPat (v1, v2) ->
      let v1 = vof_pattern v1 and v2 = vof_pattern v2 in
      OCaml.VSum ("DisjPat", [ v1; v2 ])
  | OtherPat (v1, v2) ->
      let v1 = vof_todo_kind v1 and v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("OtherPat", [ v1; v2 ])

and vof_definition (v1, v2) =
  let v1 = vof_entity v1 and v2 = vof_definition_kind v2 in
  OCaml.VTuple [ v1; v2 ]

and vof_entity { name = v_name; attrs = v_attrs; tparams = v_tparams } =
  let bnds = [] in
  let arg =
    OCaml.vof_option (vof_bracket (OCaml.vof_list vof_type_parameter)) v_tparams
  in
  let bnd = ("tparams", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_list vof_attribute v_attrs in
  let bnd = ("attrs", arg) in
  let bnds = bnd :: bnds in
  let arg = vof_entity_name v_name in
  let bnd = ("name", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

and vof_enum_entry_definition { ee_args; ee_body } =
  let bnds = [] in
  let arg = OCaml.vof_option (vof_bracket (OCaml.vof_list vof_field)) ee_body in
  let bnd = ("ee_body", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_option vof_arguments ee_args in
  let bnd = ("ee_args", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

and vof_definition_kind = function
  | EnumEntryDef v1 ->
      let v1 = vof_enum_entry_definition v1 in
      OCaml.VSum ("EnumEntryDef", [ v1 ])
  | FuncDef v1 ->
      let v1 = vof_function_definition v1 in
      OCaml.VSum ("FuncDef", [ v1 ])
  | VarDef v1 ->
      let v1 = vof_variable_definition v1 in
      OCaml.VSum ("VarDef", [ v1 ])
  | FieldDefColon v1 ->
      let v1 = vof_variable_definition v1 in
      OCaml.VSum ("FieldDefColon", [ v1 ])
  | ClassDef v1 ->
      let v1 = vof_class_definition v1 in
      OCaml.VSum ("ClassDef", [ v1 ])
  | TypeDef v1 ->
      let v1 = vof_type_definition v1 in
      OCaml.VSum ("TypeDef", [ v1 ])
  | ModuleDef v1 ->
      let v1 = vof_module_definition v1 in
      OCaml.VSum ("ModuleDef", [ v1 ])
  | MacroDef v1 ->
      let v1 = vof_macro_definition v1 in
      OCaml.VSum ("MacroDef", [ v1 ])
  | Signature v1 ->
      let v1 = vof_signature_definition v1 in
      OCaml.VSum ("Signature", [ v1 ])
  | UseOuterDecl v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("UseOuterDecl", [ v1 ])
  | OtherDef (v1, v2) ->
      let v1 = vof_todo_kind v1 in
      let v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("OtherDef", [ v1; v2 ])

and vof_module_definition { mbody = v_mbody } =
  let bnds = [] in
  let arg = vof_module_definition_kind v_mbody in
  let bnd = ("mbody", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

and vof_module_definition_kind = function
  | ModuleAlias v1 ->
      let v1 = vof_dotted_ident v1 in
      OCaml.VSum ("ModuleAlias", [ v1 ])
  | ModuleStruct (v1, v2) ->
      let v1 = OCaml.vof_option vof_dotted_name v1
      and v2 = OCaml.vof_list vof_item v2 in
      OCaml.VSum ("ModuleStruct", [ v1; v2 ])
  | OtherModule (v1, v2) ->
      let v1 = vof_todo_kind v1 and v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("OtherModule", [ v1; v2 ])

and vof_macro_definition
    { macroparams = v_macroparams; macrobody = v_macrobody } =
  let bnds = [] in
  let arg = OCaml.vof_list vof_any v_macrobody in
  let bnd = ("macrobody", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_list vof_ident v_macroparams in
  let bnd = ("macroparams", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

and vof_signature_definition { sig_tok; sig_type } =
  let bnds = [] in
  let arg = vof_type_ sig_type in
  let bnd = ("sig_type", arg) in
  let bnds = bnd :: bnds in
  let arg = vof_tok sig_tok in
  let bnd = ("sig_tok", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

and vof_type_parameter = function
  | TParamEllipsis v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("TParamEllipsis", [ v1 ])
  | TP v1 ->
      let v1 = vof_type_parameter_classic v1 in
      OCaml.VSum ("TP", [ v1 ])
  | OtherTypeParam (t, xs) ->
      let t = vof_todo_kind t and xs = OCaml.vof_list vof_any xs in
      OCaml.VSum ("OtherTypeParam", [ t; xs ])

and vof_type_parameter_classic
    {
      tp_id = v1;
      tp_attrs = v2;
      tp_bounds = v3;
      tp_default = v4;
      tp_variance = v5;
    } =
  let bnds = [] in
  let arg = OCaml.vof_option (vof_wrap vof_variance) v5 in
  let bnd = ("tp_variance", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_option vof_type_ v4 in
  let bnd = ("tp_default", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_list vof_type_ v3 in
  let bnd = ("tp_bounds", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_list vof_attribute v2 in
  let bnd = ("tp_attrs", arg) in
  let bnds = bnd :: bnds in
  let arg = vof_ident v1 in
  let bnd = ("tp_id", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

and vof_variance = function
  | Covariant -> OCaml.VSum ("Covariant", [])
  | Contravariant -> OCaml.VSum ("Contravariant", [])

and vof_function_kind = function
  | Function -> OCaml.VSum ("Function", [])
  | LambdaKind -> OCaml.VSum ("LambdaKind", [])
  | Method -> OCaml.VSum ("Method", [])
  | Arrow -> OCaml.VSum ("Arrow", [])
  | BlockCases -> OCaml.VSum ("BlockCases", [])

and vof_function_definition
    { fkind; fparams = v_fparams; frettype = v_frettype; fbody = v_fbody } =
  let bnds = [] in
  let arg = vof_function_body v_fbody in
  let bnd = ("fbody", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_option vof_type_ v_frettype in
  let bnd = ("frettype", arg) in
  let bnds = bnd :: bnds in
  let arg = vof_parameters v_fparams in
  let bnd = ("fparams", arg) in
  let bnds = bnd :: bnds in
  let arg = vof_wrap vof_function_kind fkind in
  let bnd = ("fkind", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

and vof_parameters v = vof_bracket (OCaml.vof_list vof_parameter) v

and vof_parameter = function
  | Param v1 ->
      let v1 = vof_parameter_classic v1 in
      OCaml.VSum ("Param", [ v1 ])
  | ParamRest (v0, v1) ->
      let v0 = vof_tok v0 in
      let v1 = vof_parameter_classic v1 in
      OCaml.VSum ("ParamRest", [ v0; v1 ])
  | ParamHashSplat (v0, v1) ->
      let v0 = vof_tok v0 in
      let v1 = vof_parameter_classic v1 in
      OCaml.VSum ("ParamHashSplat", [ v0; v1 ])
  | ParamPattern v1 ->
      let v1 = vof_pattern v1 in
      OCaml.VSum ("ParamPattern", [ v1 ])
  | ParamEllipsis v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("ParamEllipsis", [ v1 ])
  | ParamReceiver v1 ->
      let v1 = vof_parameter_classic v1 in
      OCaml.VSum ("ParamReceiver", [ v1 ])
  | OtherParam (v1, v2) ->
      let v1 = vof_todo_kind v1 and v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("OtherParam", [ v1; v2 ])

and vof_parameter_classic
    {
      pname = v_pname;
      pdefault = v_pdefault;
      ptype = v_ptype;
      pattrs = v_pattrs;
      pinfo = v_pinfo;
    } =
  let bnds = [] in
  let arg = vof_id_info v_pinfo in
  let bnd = ("pinfo", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_list vof_attribute v_pattrs in
  let bnd = ("pattrs", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_option vof_type_ v_ptype in
  let bnd = ("ptype", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_option vof_expr v_pdefault in
  let bnd = ("pdefault", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_option vof_ident v_pname in
  let bnd = ("pname", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

and vof_function_body = function
  | FBStmt v1 ->
      let v1 = vof_stmt v1 in
      OCaml.VSum ("FBStmt", [ v1 ])
  | FBExpr v1 ->
      let v1 = vof_expr v1 in
      OCaml.VSum ("FBExpr", [ v1 ])
  | FBDecl v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("FBDecl", [ v1 ])
  | FBNothing -> OCaml.VSum ("FBNothing", [])

and vof_variable_definition { vinit = v_vinit; vtype = v_vtype; vtok } =
  let bnds = [] in
  let arg = OCaml.vof_option vof_tok vtok in
  let bnd = ("vtok", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_option vof_type_ v_vtype in
  let bnd = ("vtype", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_option vof_expr v_vinit in
  let bnd = ("vinit", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

and vof_field = function
  | F v1 ->
      let v1 = vof_stmt v1 in
      OCaml.VSum ("F", [ v1 ])

and vof_type_definition { tbody = v_tbody } =
  let bnds = [] in
  let arg = vof_type_definition_kind v_tbody in
  let bnd = ("tbody", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

and vof_type_definition_kind = function
  | OrType v1 ->
      let v1 = OCaml.vof_list vof_or_type_element v1 in
      OCaml.VSum ("OrType", [ v1 ])
  | AndType v1 ->
      let v1 = vof_bracket (OCaml.vof_list vof_field) v1 in
      OCaml.VSum ("AndType", [ v1 ])
  | AliasType v1 ->
      let v1 = vof_type_ v1 in
      OCaml.VSum ("AliasType", [ v1 ])
  | NewType v1 ->
      let v1 = vof_type_ v1 in
      OCaml.VSum ("NewType", [ v1 ])
  | Exception (v1, v2) ->
      let v1 = vof_ident v1 and v2 = OCaml.vof_list vof_type_ v2 in
      OCaml.VSum ("Exception", [ v1; v2 ])
  | AbstractType v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("AbstractType", [ v1 ])
  | OtherTypeKind (v1, v2) ->
      let v1 = vof_todo_kind v1 and v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("OtherTypeKind", [ v1; v2 ])

and vof_or_type_element = function
  | OrConstructor (v1, v2) ->
      let v1 = vof_ident v1 and v2 = OCaml.vof_list vof_type_ v2 in
      OCaml.VSum ("OrConstructor", [ v1; v2 ])
  | OrEnum (v1, v2) ->
      let v1 = vof_ident v1 and v2 = OCaml.vof_option vof_expr v2 in
      OCaml.VSum ("OrEnum", [ v1; v2 ])
  | OrUnion (v1, v2) ->
      let v1 = vof_ident v1 and v2 = vof_type_ v2 in
      OCaml.VSum ("OrUnion", [ v1; v2 ])
  | OrEllipsis v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("OrEllipsis", [ v1 ])

and vof_class_definition
    {
      ckind = v_ckind;
      cextends = v_cextends;
      cimplements = v_cimplements;
      cbody = v_cbody;
      cmixins = v_cmixins;
      cparams;
    } =
  let bnds = [] in
  let arg = vof_bracket (OCaml.vof_list vof_field) v_cbody in
  let bnd = ("cbody", arg) in
  let bnds = bnd :: bnds in
  let arg = vof_parameters cparams in
  let bnd = ("cparams", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_list vof_type_ v_cmixins in
  let bnd = ("cmixins", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_list vof_type_ v_cimplements in
  let bnd = ("cimplements", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_list vof_class_parent v_cextends in
  let bnd = ("cextends", arg) in
  let bnds = bnd :: bnds in
  let arg = vof_class_kind v_ckind in
  let bnd = ("ckind", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

and vof_class_parent (v1, v2) =
  let v1 = vof_type_ v1 in
  let v2 = OCaml.vof_option vof_arguments v2 in
  OCaml.VTuple [ v1; v2 ]

and vof_class_kind x = vof_wrap vof_class_kind_bis x

and vof_class_kind_bis = function
  | Class -> OCaml.VSum ("Class", [])
  | Interface -> OCaml.VSum ("Interface", [])
  | Trait -> OCaml.VSum ("Trait", [])
  | Object -> OCaml.VSum ("Object", [])

and vof_ident_and_id_info (v1, v2) =
  let v1 = vof_ident v1 in
  let v2 = vof_id_info v2 in
  OCaml.VTuple [ v1; v2 ]

and vof_directive { d; d_attrs } =
  let bnds = [] in
  let arg = vof_directive_kind d in
  let bnd = ("d", arg) in
  let bnds = bnd :: bnds in
  let arg = OCaml.vof_list vof_attribute d_attrs in
  let bnd = ("d_attrs", arg) in
  let bnds = bnd :: bnds in
  OCaml.VDict bnds

and vof_directive_kind = function
  | ImportFrom (t, v1, v2) ->
      let t = vof_tok t in
      let v1 = vof_module_name v1 in
      let v2 = OCaml.vof_list vof_alias v2 in
      OCaml.VSum ("ImportFrom", [ t; v1; v2 ])
  | ImportAs (t, v1, v2) ->
      let t = vof_tok t in
      let v1 = vof_module_name v1
      and v2 = OCaml.vof_option vof_ident_and_id_info v2 in
      OCaml.VSum ("ImportAs", [ t; v1; v2 ])
  | ImportAll (t, v1, v2) ->
      let t = vof_tok t in
      let v1 = vof_module_name v1 and v2 = vof_tok v2 in
      OCaml.VSum ("ImportAll", [ t; v1; v2 ])
  | Package (t, v1) ->
      let t = vof_tok t in
      let v1 = vof_dotted_ident v1 in
      OCaml.VSum ("Package", [ t; v1 ])
  | PackageEnd t ->
      let t = vof_tok t in
      OCaml.VSum ("PackageEnd", [ t ])
  | Pragma (v1, v2) ->
      let v1 = vof_ident v1 and v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("Pragma", [ v1; v2 ])
  | OtherDirective (v1, v2) ->
      let v1 = vof_todo_kind v1 and v2 = OCaml.vof_list vof_any v2 in
      OCaml.VSum ("OtherDirective", [ v1; v2 ])

and vof_alias (v1, v2) =
  let v1 = vof_ident v1 and v2 = OCaml.vof_option vof_ident_and_id_info v2 in
  OCaml.VTuple [ v1; v2 ]

and vof_item x = vof_stmt x
and vof_program v = OCaml.vof_list vof_item v

and vof_partial = function
  | PartialMatch (v1, v2) ->
      let v1 = vof_tok v1 in
      let v2 = vof_expr v2 in
      OCaml.VSum ("PartialMatch", [ v1; v2 ])
  | PartialLambdaOrFuncDef v1 ->
      let v1 = vof_function_definition v1 in
      OCaml.VSum ("PartialLambdaOrFuncDef", [ v1 ])
  | PartialDef v1 ->
      let v1 = vof_definition v1 in
      OCaml.VSum ("PartialDef", [ v1 ])
  | PartialIf (v1, v2) ->
      let v1 = vof_tok v1 in
      let v2 = vof_expr v2 in
      OCaml.VSum ("PartialIf", [ v1; v2 ])
  | PartialTry (v1, v2) ->
      let v1 = vof_tok v1 in
      let v2 = vof_stmt v2 in
      OCaml.VSum ("PartialTry", [ v1; v2 ])
  | PartialFinally (v1, v2) ->
      let v1 = vof_tok v1 in
      let v2 = vof_stmt v2 in
      OCaml.VSum ("PartialFinally", [ v1; v2 ])
  | PartialCatch v1 ->
      let v1 = vof_catch v1 in
      OCaml.VSum ("PartialCatch", [ v1 ])
  | PartialSingleField (v1, v2, v3) ->
      let v1 = vof_wrap OCaml.vof_string v1 in
      let v2 = vof_tok v2 in
      let v3 = vof_expr v3 in
      OCaml.VSum ("PartialSingleField", [ v1; v2; v3 ])
  | PartialSwitchCase v1 ->
      let v1 = vof_case_and_body v1 in
      OCaml.VSum ("PartialSwitchCase", [ v1 ])

and vof_any = function
  | Raw v1 ->
      let v1 = vof_raw_tree v1 in
      OCaml.VSum ("Raw", [ v1 ])
  | Name v1 ->
      let v1 = vof_name v1 in
      OCaml.VSum ("Name", [ v1 ])
  | Xmls v1 ->
      let v1 = OCaml.vof_list vof_xml_body v1 in
      OCaml.VSum ("Xmls", [ v1 ])
  | ForOrIfComp v1 ->
      let v1 = vof_for_or_if_comp v1 in
      OCaml.VSum ("ForOrIfComp", [ v1 ])
  | Tp v1 ->
      let v1 = vof_type_parameter v1 in
      OCaml.VSum ("Tp", [ v1 ])
  | Ta v1 ->
      let v1 = vof_type_argument v1 in
      OCaml.VSum ("Ta", [ v1 ])
  | Cs v1 ->
      let v1 = vof_case v1 in
      OCaml.VSum ("Cs", [ v1 ])
  | Str v1 ->
      let v1 = vof_bracket (vof_wrap OCaml.vof_string) v1 in
      OCaml.VSum ("Str", [ v1 ])
  | Args v1 ->
      let v1 = OCaml.vof_list vof_argument v1 in
      OCaml.VSum ("Args", [ v1 ])
  | Params v1 ->
      let v1 = OCaml.vof_list vof_parameter v1 in
      OCaml.VSum ("Params", [ v1 ])
  | Flds v1 ->
      let v1 = OCaml.vof_list vof_field v1 in
      OCaml.VSum ("Flds", [ v1 ])
  | Anys v1 ->
      let v1 = OCaml.vof_list vof_any v1 in
      OCaml.VSum ("Anys", [ v1 ])
  | Partial v1 ->
      let v1 = vof_partial v1 in
      OCaml.VSum ("Partial", [ v1 ])
  | TodoK v1 ->
      let v1 = vof_ident v1 in
      OCaml.VSum ("TodoK", [ v1 ])
  | Tk v1 ->
      let v1 = vof_tok v1 in
      OCaml.VSum ("Tk", [ v1 ])
  | Modn v1 ->
      let v1 = vof_module_name v1 in
      OCaml.VSum ("Modn", [ v1 ])
  | ModDk v1 ->
      let v1 = vof_module_definition_kind v1 in
      OCaml.VSum ("ModDk", [ v1 ])
  | En v1 ->
      let v1 = vof_entity v1 in
      OCaml.VSum ("En", [ v1 ])
  | E v1 ->
      let v1 = vof_expr v1 in
      OCaml.VSum ("E", [ v1 ])
  | S v1 ->
      let v1 = vof_stmt v1 in
      OCaml.VSum ("S", [ v1 ])
  | Ss v1 ->
      let v1 = OCaml.vof_list vof_stmt v1 in
      OCaml.VSum ("Ss", [ v1 ])
  | T v1 ->
      let v1 = vof_type_ v1 in
      OCaml.VSum ("T", [ v1 ])
  | P v1 ->
      let v1 = vof_pattern v1 in
      OCaml.VSum ("P", [ v1 ])
  | Def v1 ->
      let v1 = vof_definition v1 in
      OCaml.VSum ("D", [ v1 ])
  | Dir v1 ->
      let v1 = vof_directive v1 in
      OCaml.VSum ("Di", [ v1 ])
  | Fld v1 ->
      let v1 = vof_field v1 in
      OCaml.VSum ("Fld", [ v1 ])
  | Di v1 ->
      let v1 = vof_dotted_name v1 in
      OCaml.VSum ("Dn", [ v1 ])
  | I v1 ->
      let v1 = vof_ident v1 in
      OCaml.VSum ("I", [ v1 ])
  | Pa v1 ->
      let v1 = vof_parameter v1 in
      OCaml.VSum ("Pa", [ v1 ])
  | Ce v1 ->
      let v1 = vof_catch_exn v1 in
      OCaml.VSum ("Ce", [ v1 ])
  | Ar v1 ->
      let v1 = vof_argument v1 in
      OCaml.VSum ("Ar", [ v1 ])
  | At v1 ->
      let v1 = vof_attribute v1 in
      OCaml.VSum ("At", [ v1 ])
  | XmlAt v1 ->
      let v1 = vof_xml_attribute v1 in
      OCaml.VSum ("XmlAt", [ v1 ])
  | Dk v1 ->
      let v1 = vof_definition_kind v1 in
      OCaml.VSum ("Dk", [ v1 ])
  | Pr v1 ->
      let v1 = vof_program v1 in
      OCaml.VSum ("Pr", [ v1 ])
  | Lbli v1 ->
      let v1 = vof_label_ident v1 in
      OCaml.VSum ("Lbli", [ v1 ])

and vof_raw_tree x =
  match x with
  | Token v ->
      let v = vof_wrap OCaml.vof_string v in
      OCaml.VSum ("Token", [ v ])
  | List v ->
      let v = (OCaml.vof_list vof_raw_tree) v in
      OCaml.VSum ("List", [ v ])
  | Tuple v ->
      let v = (OCaml.vof_list vof_raw_tree) v in
      OCaml.VSum ("Tuple", [ v ])
  | Case (v1, v2) ->
      let v1 = OCaml.vof_string v1 in
      let v2 = vof_raw_tree v2 in
      OCaml.VSum ("Case", [ v1; v2 ])
  | Option v ->
      let v = (OCaml.vof_option vof_raw_tree) v in
      OCaml.VSum ("Option", [ v ])
  | Any v ->
      let v = vof_any v in
      OCaml.VSum ("Any", [ v ])
